package cluster

import (
	"context"
	"fmt"
	"sync"
	"time"
)

// Manager 是集群管理器接口
type Manager interface {
	// Start 启动集群管理器
	Start(ctx context.Context) error
	// Stop 停止集群管理器
	Stop(ctx context.Context) error
	// Join 加入集群
	Join(ctx context.Context, addresses []string) error
	// Leave 离开集群
	Leave(ctx context.Context) error
	// GetNodes 获取集群节点
	GetNodes(ctx context.Context) ([]*NodeInfo, error)
	// GetNode 获取指定节点
	GetNode(ctx context.Context, nodeID string) (*NodeInfo, error)
	// GetLocalNode 获取本地节点
	GetLocalNode(ctx context.Context) (*NodeInfo, error)
	// IsLeader 检查本地节点是否为领导者
	IsLeader(ctx context.Context) (bool, error)
	// GetLeader 获取领导者节点
	GetLeader(ctx context.Context) (*NodeInfo, error)
	// Subscribe 订阅集群事件
	Subscribe(ctx context.Context, eventType string) (<-chan Event, error)
	// Unsubscribe 取消订阅集群事件
	Unsubscribe(ctx context.Context, eventType string, ch <-chan Event) error
	// Broadcast 广播消息到集群
	Broadcast(ctx context.Context, message []byte) error
	// Send 发送消息到指定节点
	Send(ctx context.Context, nodeID string, message []byte) error
	// SetMetadata 设置节点元数据
	SetMetadata(ctx context.Context, key string, value string) error
	// GetMetadata 获取节点元数据
	GetMetadata(ctx context.Context, nodeID string, key string) (string, error)
}

// Event 是集群事件
type Event struct {
	// Type 是事件类型
	Type string
	// NodeID 是相关节点ID
	NodeID string
	// Node 是相关节点信息
	Node *NodeInfo
	// Timestamp 是事件时间戳
	Timestamp time.Time
	// Data 是事件数据
	Data map[string]interface{}
}

// EventType 是事件类型
const (
	// EventTypeNodeJoin 表示节点加入事件
	EventTypeNodeJoin = "node_join"
	// EventTypeNodeLeave 表示节点离开事件
	EventTypeNodeLeave = "node_leave"
	// EventTypeNodeFailed 表示节点失败事件
	EventTypeNodeFailed = "node_failed"
	// EventTypeNodeUpdate 表示节点更新事件
	EventTypeNodeUpdate = "node_update"
	// EventTypeLeaderElected 表示领导者选举事件
	EventTypeLeaderElected = "leader_elected"
	// EventTypeLeaderChanged 表示领导者变更事件
	EventTypeLeaderChanged = "leader_changed"
	// EventTypeClusterChanged 表示集群变更事件
	EventTypeClusterChanged = "cluster_changed"
)

// ManagerFactory 是创建集群管理器的工厂
type ManagerFactory func(config *Config) (Manager, error)

// Config 是集群管理器配置
type Config struct {
	// NodeID 是节点ID
	NodeID string
	// BindAddress 是绑定地址
	BindAddress string
	// AdvertiseAddress 是广播地址
	AdvertiseAddress string
	// SeedAddresses 是种子节点地址
	SeedAddresses []string
	// Role 是节点角色
	Role string
	// Tags 是节点标签
	Tags []string
	// Metadata 是节点元数据
	Metadata map[string]string
	// HeartbeatInterval 是心跳间隔
	HeartbeatInterval time.Duration
	// HeartbeatTimeout 是心跳超时
	HeartbeatTimeout time.Duration
	// JoinTimeout 是加入超时
	JoinTimeout time.Duration
	// LeaveTimeout 是离开超时
	LeaveTimeout time.Duration
	// EnableCompression 是否启用压缩
	EnableCompression bool
	// EnableEncryption 是否启用加密
	EnableEncryption bool
	// EncryptionKey 是加密密钥
	EncryptionKey string
	// LogLevel 是日志级别
	LogLevel string
}

// DefaultConfig 返回默认配置
func DefaultConfig() *Config {
	return &Config{
		BindAddress:       "0.0.0.0:7946",
		HeartbeatInterval: 1 * time.Second,
		HeartbeatTimeout:  5 * time.Second,
		JoinTimeout:       10 * time.Second,
		LeaveTimeout:      5 * time.Second,
		EnableCompression: true,
		LogLevel:          "info",
		Metadata:          make(map[string]string),
	}
}

// Validate 验证配置
func (c *Config) Validate() error {
	if c.BindAddress == "" {
		return fmt.Errorf("bind address is required")
	}

	if c.HeartbeatInterval <= 0 {
		return fmt.Errorf("heartbeat interval must be positive")
	}

	if c.HeartbeatTimeout <= 0 {
		return fmt.Errorf("heartbeat timeout must be positive")
	}

	if c.JoinTimeout <= 0 {
		return fmt.Errorf("join timeout must be positive")
	}

	if c.LeaveTimeout <= 0 {
		return fmt.Errorf("leave timeout must be positive")
	}

	return nil
}

// registry 是集群管理器工厂注册表
var (
	registry = make(map[string]ManagerFactory)
	mu       sync.RWMutex
)

// RegisterManagerFactory 注册集群管理器工厂
func RegisterManagerFactory(name string, factory ManagerFactory) {
	mu.Lock()
	defer mu.Unlock()
	registry[name] = factory
}

// GetManagerFactory 获取集群管理器工厂
func GetManagerFactory(name string) (ManagerFactory, bool) {
	mu.RLock()
	defer mu.RUnlock()
	factory, ok := registry[name]
	return factory, ok
}

// ListManagerFactories 列出所有集群管理器工厂
func ListManagerFactories() []string {
	mu.RLock()
	defer mu.RUnlock()
	names := make([]string, 0, len(registry))
	for name := range registry {
		names = append(names, name)
	}
	return names
}

// NewManager 创建集群管理器
func NewManager(managerType string, config *Config) (Manager, error) {
	factory, ok := GetManagerFactory(managerType)
	if !ok {
		return nil, fmt.Errorf("unknown cluster manager type: %s", managerType)
	}
	return factory(config)
}
